package cn.itcast.nems.common.web.filter;

import cn.itcast.ic.common.bean.BizError;
import cn.itcast.ic.common.exception.BizException;
import com.fasterxml.jackson.databind.json.JsonMapper;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * 过滤所有请求中的异常
 * author: yong.li
 * create: 2021-10-20 09:58:18
 **/
public class ExceptionFilter implements Filter {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    private final JsonMapper jsonMapper = new JsonMapper();

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException {
        try {
            chain.doFilter(request, response);
        } catch (Throwable e) {
            logger.warn(e.getMessage(), e);
            if (!response.isCommitted()) {
                BizException eae = this.findBizException(e);
                String msg = "服务器出错";
                String code = BizError.SERVICE_ERROR.getCode();
                int httpStatus = BizError.SERVICE_ERROR.getStatus();
                if (eae != null) {
                    msg = eae.getMessage();
                    final BizError error = eae.getError();
                    if (error != null) {
                        msg = error.getMessage();
                        code = error.getCode();
                        httpStatus = error.getStatus();
                    }
                }
                Map<String, Object> res = new HashMap<>();
                res.put("code", code);
                res.put("message", msg);
                res.put("datetime", LocalDateTime.now().toString());
                final String result = jsonMapper.writeValueAsString(res);
                HttpServletResponse httpResponse = (HttpServletResponse) response;
                httpResponse.setContentType("application/json");
                httpResponse.setStatus(httpStatus);
                httpResponse.setCharacterEncoding("UTF-8");
                response.getWriter().write(result);
            }
        }
    }

    private BizException findBizException(Throwable throwable) {
        BizException uce = null;
        Throwable e = throwable;
        do {
            if (e instanceof BizException) {
                uce = (BizException) e;
                break;
            }
            e = e.getCause();
        } while (e != null);
        return uce;
    }
}
